// Singleton
// (c) jimon game studio

#ifndef JEH_JESINGLETON
#define JEH_JESINGLETON

#include "Config_Engine.h"
#include "jeTypes.h"
#include "jeMemory.h"
#include "jeThreads.h"
#include "jeDebug.h"

namespace je
{
	// use for internal singletons (no export)
	#define DECLARE_SINGLETON(type)	I##type * Get##type();\
									void CreateSingleton##type();\
									I##type ** Get##type##Pointer();

	// use for internal singletons with no interface
	#define DECLARE_SINGLETON_FULLNAME(type)	type * Get##type();\
												void CreateSingleton##type();\
												type ** Get##type##Pointer();

	// base export singleton
	#define DECLARE_SINGLETON_E(ex,excall,type)	ex I##type * excall Get##type();\
												ex void excall CreateSingleton##type();\
												ex I##type ** excall Get##type##Pointer();

	// implement base singleton (or internal)
	#define IMPLEMENT_SINGLETON(type,excall)	I##type * _self_##type = NULL;\
												I##type * excall Get##type(){return _self_##type;}\
												void excall CreateSingleton##type(){JENEW( _self_##type, C##type );}\
												I##type ** excall Get##type##Pointer(){return &_self_##type;}\
												void Set##type(I##type * _self){if (_self_##type && ( _self != NULL)){JEBREAK(1)}\
													_self_##type = _self;}

	// use when implemenation of base or internal signeton has different name (has not C##name)
	#define IMPLEMENT_SINGLETON_N(type,typerel,excall)	I##type * _self_##type = NULL;\
														I##type * excall Get##type(){return _self_##type;}\
														void excall CreateSingleton##type(){JENEW( _self_##type, typerel );}\
														I##type ** excall Get##type##Pointer(){return &_self_##type;}\
														void Set##type(I##type * _self){if (_self_##type && ( _self != NULL)){JEBREAK(1)}\
															_self_##type = _self;}

	// impelement singleton with fullname
	#define IMPLEMENT_SINGLETON_FULLNAME(type,excall)	type * _self_##type = NULL;\
														type * excall Get##type(){return _self_##type;}\
														void excall CreateSingleton##type(){JENEW( _self_##type, type );}\
														type ** excall Get##type##Pointer(){return &_self_##type;}\
														void Set##type(type * _self){if (_self_##type && ( _self != NULL)){JEBREAK(1)}\
														_self_##type = _self;}
}

#endif
